package com.smh.demo1.a05;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.List;
import java.util.Set;

/**
 * @author shiminghui
 * @date 2025/4/11 17:57
 * @description: TODO
 */
public class MyConfigurationClassPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        try {
            handlerComponentScanner(configurableListableBeanFactory);
            HandlerBeanAnnotation(configurableListableBeanFactory);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    private void handlerComponentScanner(ConfigurableListableBeanFactory configurableListableBeanFactory) throws IOException {
        // 模拟实现ConfigurationClassPostProcessor的效果
        // 1. 获取@ComponentScan注解  (这里仅仅是扫描了Config这个类,真实情况下会逐个扫描所有的类)
        ComponentScan annotation = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
        // 2. 获取@ComponentScan注解的basePackages属性
        if (annotation != null) {
            String[] strings = annotation.basePackages();
            AnnotationBeanNameGenerator nameGenerator = new AnnotationBeanNameGenerator(); // 用于生成beanName
            // 处理每一个basePackages属性
            for (String string : strings) {
//                System.out.println(string);
                // 生成一个路径
                String s = "classpath*:" + string.replace(".", "/") + "/**/*.class";
//                System.out.println(s);
                Resource[] resources = new PathMatchingResourcePatternResolver().getResources(s);

                CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
                for (Resource resource : resources) {
//                    System.out.println(resource);
                    // 解析resource
                    MetadataReader metadataReader = readerFactory.getMetadataReader(resource);

                    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                    boolean b = annotationMetadata.hasAnnotation(Component.class.getName());
                    boolean b1 = annotationMetadata.hasMetaAnnotation(Component.class.getName()); // 派生注解
                    if (b || b1) {
                        // 将resource对应的bean注册到容器中
                        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();

                        if (configurableListableBeanFactory instanceof DefaultListableBeanFactory beanFactory) {
                            String beanName = nameGenerator.generateBeanName(beanDefinition, beanFactory);
                            beanFactory.registerBeanDefinition(beanName, beanDefinition);
                        }
                    }
                }
            }
        }
    }

    private void HandlerBeanAnnotation(ConfigurableListableBeanFactory configurableListableBeanFactory) throws IOException {
        // 模拟@bean的注解解析
        CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
        MetadataReader metadataReader = readerFactory.getMetadataReader(Config.class.getName());
        Set<MethodMetadata> annotatedMethods =
                metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata annotatedMethod : annotatedMethods) {
//            System.out.println(annotatedMethod.getMethodName());
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
            builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); // 设置自动注入,对于构造方法和工厂方法参数,选择构造方法类型
            builder.setFactoryMethodOnBean(annotatedMethod.getMethodName(), "config"); // 设置工厂方法,参数为方法名和工厂类名
            AbstractBeanDefinition db = builder.getBeanDefinition();

            if (configurableListableBeanFactory instanceof DefaultListableBeanFactory beanFactory) {
                beanFactory.registerBeanDefinition(annotatedMethod.getMethodName(), db); // 注册bean,bean的名字是方法名
            }

            // 解析Bean注解的参数,并处理
            List<Object> initMethod = annotatedMethod.getAllAnnotationAttributes(Bean.class.getName()).get("initMethod");
            if (initMethod != null && !initMethod.isEmpty()) {
                String string = (String) initMethod.get(0);
                if (StringUtils.hasLength(string)) {
//                    System.out.println("初始化的方法名"+string);
                    db.setInitMethodName(string);
                }
            }
        }
    }
}
